import operator
import sys
import traceback

class ConfigurationError(Exception):
	pass

class ValidationError(Exception):
	pass

class Config(dict):
	def __init__(self, config, env=dict(), postprocess=lambda x: x):
		try:
			config_contents = reduce(operator.add, file(config))
		except TypeError:
			config_contents = reduce(operator.add, config)
			config = repr(config)

		if type(env) is not dict:
			raise TypeError("'env' argument must be a dictionary.")

		try:
			config_code = compile(config_contents, config, 'exec')
		except SyntaxError, e:
			if e.filename == config:
				raise ConfigurationError(
				"Syntax Error (line %d):" % e.lineno +
				"\n\t%s" % e.text.strip() +
				"\n\t%s^" % (' ' * (e.offset - 2)))
			else:
				raise

		config_data = {}

		try:
			eval(config_code, env, config_data)
		except StandardError, e:
			raise ConfigurationError(e)

		try:
			postprocess(config_data)
		except (ValidationError, AssertionError), e:
			raise ValidationError(e)

		self.update(config_data)
